using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;

namespace BlobSim
{
    class SwipeAccumulator
    {
        public const float DefaultSwipeResidueTime = 0.2f;

        private float _swipeResidueTime;

        private List<TouchMove> moves;

        public SwipeAccumulator()
        {
            moves = new List<TouchMove>();
            setDefaultValues();
        }

        private void setDefaultValues()
        {
            _swipeResidueTime = DefaultSwipeResidueTime;
        }

        public float SwipeResidueTime
        {
            get { return _swipeResidueTime; }
            set
            {
                if (value <= 0)
                    throw new ArgumentOutOfRangeException("value", "value must be greater than zero");
                
                _swipeResidueTime = value;
            }
        }

        public void AddTouchMove(Vector2 delta, TimeSpan elapsedGameTime)
        {
            moves.Add(new TouchMove {Delta = delta, Elapsed = (float) elapsedGameTime.TotalSeconds});
            clearUnneededMoves();
        }

        public bool IsEmpty()
        {
            return moves.Count == 0;
        }

        public void ClearTouchMoves()
        {
            moves.Clear();
        }

        private void clearUnneededMoves()
        {
            var relevantTime = _swipeResidueTime;
            var idx = moves.Count - 1;

            while (relevantTime > 0 && idx >= 0)
                relevantTime -= moves[idx--].Elapsed;

            while (idx-- > 0)
                moves.RemoveAt(0);
        }

        public Vector2 GetSwipeResidue()
        {
            var timeUsed = 0.0f;
            var idx = moves.Count - 1;
            var swipe = Vector2.Zero;
            while (timeUsed < _swipeResidueTime && idx >= 0)
            {
                var newChunk = moves[idx].Elapsed;
                if (timeUsed + newChunk > _swipeResidueTime)
                {
                    newChunk = _swipeResidueTime - timeUsed;
                }
                timeUsed += newChunk;

                swipe += moves[idx].Delta*newChunk;

                idx--;
            }

            if (timeUsed == 0.0f) return Vector2.Zero;

            return swipe/timeUsed;
        }

        struct TouchMove
        {
            public Vector2 Delta;
            public float Elapsed;
        }
    }
}
